const std = @import("std");

pub const PostAcceptInfo = struct {
    endpoint: std.net.Address,
};

pub const PostReadInfo = struct {
    endpoint: std.net.Address,
    buf: [4096]u8,
    fd: std.os.fd_t,
};

pub const PostWriteInfo = struct {
    endpoint: std.net.Address,
    buf: [4096]u8,
    fd: std.os.fd_t,
};

pub const PostCloseInfo = struct {
    endpoint: std.net.Address,
};

pub const State = union(enum) {
    PostAccept: PostAcceptInfo,
    PostRead: PostReadInfo,
    PostWrite: PostWriteInfo,
    PostClose: PostCloseInfo,
    Ready: void,
};

pub const IO = struct {
    const Self = @This();

    pub const BACKLOG = 64;
    pub const PORT = 51820;

    listener: std.net.StreamServer,
    ring: std.os.linux.IO_Uring,
    states: [BACKLOG]State,

    pub fn init() Self {
        return Self {
            .listener = std.net.StreamServer.init(.{
                .kernel_backlog = BACKLOG,
                .reuse_address = true,
            }),
            .ring = undefined,
            .states = [_]State{.{.Ready = {}}} ** BACKLOG,
        };
    }

    pub fn setup(self: *Self) !void {
        var addr = try std.net.Address.parseIp("0.0.0.0", PORT);
        try self.listener.listen(addr);
        self.ring = try std.os.linux.IO_Uring.init(BACKLOG, 0);
    }
};